package org.bleep.physics;

/**
* <p>Represents a 2-dimensional vector of floats, providing common methods for retrieving
* the vector's magnitude and angle.  Static methods are provided for performing vector
* arithmetic without permanently changing a vector.</p>
* <p>Vector2D objects are used to represent position, velocity, acceleration, and
* any number of other physics related values where a magnitude (<em>speed</em>, or
* <em>force</em>, for example) and a direction are required.</p>
* 
* @author John Cromartie
*/
public class Vector2D
{
	public static Vector2D UP = new Vector2D(0f, -1f);
	public static Vector2D DOWN = new Vector2D(0f, 1f);
	public static Vector2D LEFT = new Vector2D(-1f, 0f);
	public static Vector2D RIGHT = new Vector2D(1f, 0f);
	public static Vector2D ZERO = new Vector2D(0f, 0f);
	
	private float x;
	private float y;
	
	/**
	* <p>Create a new Vector2D object with default X and Y components of 0.0f.</p>
	*/
	public Vector2D()
	{
		x = 0f;
		y = 0f;
	}
	
	/**
	* <p>Create a new Vector2D object with the specified X and Y components</p>
	* @param x	the X (horizontal) component of the vector
	* @param y	the Y (vertical) component of the vector
	*/
	public Vector2D(float x, float y)
	{
		this.x = x;
		this.y = y;
	}
	
	/**
	* <p>Create a new Vector2D from magnitude and angle values.  Calculates the X
	* and Y components as <em>cos(angle) * mag</em> and <em>sin(angle) * mag</em>
	* respectively.</p>
	* @param mag magnitude of vector
	* @param angle angle of vector
	* @return a new vector
	*/
	public static Vector2D withMagAndAngle(float mag, double angle)
	{
		return new Vector2D((float)Math.cos(angle) * mag, (float)Math.sin(angle) * mag);
	}
	
	/**
	* <p>Returns the positive magnitude of the vector, as computed by sqrt(x^2 + y^2).</p>
	* @return magnitude of the vector
	*/
	public float getMagnitude()
	{
		return (float)Math.sqrt(x * x + y * y);
	}
	
	/**
	* <p>Returns the angle of the vector, as computed by atan(y / x)</p>
	* @return angle of the vector (in radians)
	*/
	public double getAngle()
	{
		return Math.atan((double)(y / x));
	}
	
	/**
	* <p>Gets the X component of the vector.</p>
	* @return X component
	*/
	public float getX()
	{
		return x;
	}
	
	/**
	* <p>Gets the Y component of the vector.</p>
	* @return Y component
	*/
	public float getY()
	{
		return y;
	}
	
	public void setX(float x)
	{
		this.x = x;
	}
	
	public void setY(float y)
	{
		this.y = y;
	}
	
	/**
	* <p>Add another vector to the vector.</p>
	* @param v Vector2D to be added
	*/
	public void add(Vector2D v)
	{
		x += v.getX();
		y += v.getY();
	}
	
	public void zero()
	{
		x = 0.0f;
		y = 0.0f;
	}
	
	/**
	* <p>Subtracts another vector from this.</p>
	* @param v Vector to be subtracted from this
	*/
	public void sub(Vector2D v)
	{
		x -= v.getX();
		y -= v.getY();
	}
	
	public void mult(float n)
	{
		x *= n;
		y *= n;
	}
	
	public void div(float n)
	{
		x /= n;
		y /= n;
	}
	
	/**
	* <p>Normalize this vector.  Normalizing a vector ensures a magnitude of 1
	* while maintaining its direction.</p>
	*/
	public void normalize()
	{
		float mag = getMagnitude();
		if (mag != 0f)
		{
			x /= mag;
			y /= mag;
		}
		else
		{
			x = 1f;
			y = 0f;
		}
	}
	
	public static Vector2D mult(Vector2D v, float n)
	{
		return new Vector2D(v.getX() * n, v.getY() * n);
	}
	
	public String toString()
	{
		return "x: " + x + ", y: " + y;
	}
}